package cn.virens.app.main;

import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Timer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.setting.Setting;

public abstract class AppLoad implements Component {
	protected final static Logger logger = LoggerFactory.getLogger(AppLoad.class);

	/** 定时器 统一延时30秒执行 */
	private final static int delay = 30 * 1000;

	private final static List<Component> components = new ArrayList<>();
	private final static Runtime runtime = Runtime.getRuntime();
	private final static AppInfo info = new AppInfo();
	private final static Timer timer = new Timer();

	protected static <T extends AppLoad> void load(T app) throws Exception {
		logger.debug("The Server starting...");

		// 获取配置内容
		Setting setting = new Setting("config.setting");

		// 打印配置内容
		for (Entry<String, String> entry : setting.entrySet()) {
			logger.info("Load config->" + entry.getKey() + "=" + entry.getValue());
		}

		// 读取应用配置内容
		info.setAuth(RandomUtil.randomString(32));
		info.setType(setting.getStr("app.type"));
		info.setName(setting.getStr("app.name"));

		// 绑定应用退出钩子
		runtime.addShutdownHook(new Thread(() -> {
			try {
				logger.debug("The Server stoping...");

				logger.debug("Stop Timer...");
				timer.cancel();

				// 将被管理的生命周期组件统一销毁
				logger.debug("Stop Components...");
				for (Component component : components) {
					destroy(component);
				}

				logger.debug("Stoped Components:" + components.size());
				logger.debug("Stop App...");
				// 执行应用销毁
				app.destroy();
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			} finally {
				logger.debug("The Server stoped.");
			}
		}));

		logger.debug("Load App...");

		// 启动应用
		app.start(setting);
		app.initialize();

		// 将被管理的生命周期组件统一初始化
		logger.debug("Load Components...");
		for (Component component : components) {
			initialize(component);
		}

		logger.debug("Loaded Components:" + components.size());

		// 获取应用运行信息
		String runInf = ManagementFactory.getRuntimeMXBean().getName();
		String[] runInfo = runInf.split("@", 2);

		logger.debug("The Server pid:" + runInfo[0]);
		logger.debug("The Server pkg:" + runInfo[1]);
		logger.debug("The Server started.");
		logger.debug("The Server runing...");
	}

	/**
	 * 获取 应用信息
	 * 
	 * @return
	 */
	public synchronized static AppInfo info() {
		return info;
	}

	/** 应用信息 - 应用认证 */
	public synchronized static String appAuth() {
		return info.auth();
	}

	/** 应用信息 - 应用类型 */
	public synchronized static String[] appType() {
		return info.type();
	}

	/** 应用信息 - 应用名称 */
	public synchronized static String appName() {
		return info.name();
	}

	/**
	 * 插件 生命周期管理
	 * 
	 * @param  component 自定义组件
	 * @return
	 */
	public synchronized static <T extends Component> T register(T component) {
		return components.add(component) ? component : null;
	}

	/**
	 * 启动 业务定时器
	 * 
	 * @param task   定时任务
	 * @param period 执行周期
	 */
	public synchronized static void schedule(ComponentTimer<?> task, long period) {
		timer.schedule(task, delay, period * 1000);
	}

	protected abstract void start(Setting setting);

	/** 调用组件的 初始化事件 */
	private static void initialize(Component cmpt) {
		logger.debug("Load Component->" + cmpt.name());

		try {
			cmpt.initialize();
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
	}

	/** 调用组件的 销毁事件 */
	private static void destroy(Component cmpt) {
		logger.debug("Stop Component->" + cmpt.name());

		try {
			cmpt.destroy();
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
	}

}
